package edu.bu.cs511.p5;

/**
 * The purpose of this class is to output the amount of CPU different
 * tasks received when run through a specific scheduling hierarchy.
 * It assumes that tasks have names as specified below, and that
 * whenever they run they print out their name. <p/>
 *
 * TestTaskPercentages takes a file that contains scheduler task
 * output with the following formatting rules:<p/>
 *
 * 1) Each opcode must print out an identification whenever run into
 * the file.<p/>
 * 
 * 2) That identification has a unique character for every scheduler
 * above that opcode.<p/>
 * 
 * 3) each character in the ID corresponds to either the opcode, or a
 * scheduler above it. Characters corresponding to schedulers above
 * the opcode must be uniform across tasks under that scheduler.<p/>
 *
 * 4) all of these symbols are on the same line with no extraneous
 * characters such as spaces.<p/>
 *
 * So for instance, in the hierarchy:<p/>
 * <pre>
 * opcode1 opcode2  opcode3
 *     |    |         |
 *     sched1        sched2
 *          |        |
 *          +-sched3-+
 * 
 * opcode1 could have the id "1a"
 * opcode2 "2a"
 * opcode3 "1b"
 * <pre/>
 * 
 * Given a file with this format, we will output meaningful results 
 * for the percentage of each characters appearance in the file.  This
 * can be used to numerically compare against expected execution
 * amounts to see if the schedulers are working.
 */

import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;

class TestTaskPercentages {
    /**
     * Return a string containing all characters that are present in
     * the output data.<p/>
     *
     * @REQUIRES fileData must contain a string conforming to the
     * rules listed in this class's introduction.<p/>
     *
     * @EFFECTS Return a string containing only those characters which
     * are present in fileData.
     */
    public static String charactersPresent(String fileData) {
        String present = "";

        for (int i = 0; i < fileData.length(); i++) {
            String character;
            character = fileData.substring(i, i + 1);

            /* if this character hasnt been found yet, add it */
            if (present.indexOf(character) == -1) {
                present = present + character;
            }
        }

        return present;
    }

    /**
     * Take the file conforming to the rules listed in the class's
     * introduction, and a string of all of the unique characters in
     * that output and return an array of the number of occurences of
     * each of those unique characters.<p/>
     *
     * @REQUIRES fileData must be the program output conforming to the
     * specs given at the beginning of the class, and allCharacters is
     * a string of the unique characters of that fileData.<p/>
     *
     * @EFFECTS Return an array sorted with respect to the unique
     * character string with each element equal to the amount of times
     * each unique character appeared in fileData.
     */
    public static int[] countFrequency(String fileData, String allCharacters) {
        int frequency[] = new int[allCharacters.length()];

        for (int i = 0; i < fileData.length(); i++) {
            String character;
            int index;

            character = fileData.substring(i, i + 1);
            index = allCharacters.indexOf(character);

            if (index == -1) {
                System.out.println("BUG: have found a character not in the allCharacters string.");
                continue;
            }

            frequency[index]++;
        }

        return frequency;
    }

    /**
     * Print out the data including the frequency of appearance of
     * each character.  This output can be used to deduce if each task
     * is getting the appropriate amount of CPU share based on its
     * schedulers and its parameters within those schedulers.<p/>
     *
     * @REQUIRES allCharacters is the string of all the unique
     * characters and frequency is the array of its returned from
     * countFrequency (for example).
     *
     * @MODIFIES Print out the frequency of execution of each of those
     * unique characters, thus tasks.
     */
    public static void outputData(String allCharacters, int [] frequency) {
        int total = 0;

        System.out.print("Unique characters are: ");
        System.out.println(allCharacters);
        System.out.println("Their frequency is:");

        for (int i = 0; i < frequency.length; i++) {
            total += frequency[i];
        }
	/* total should be half as large as we have schedulers AND
	 * opcodes. */
	total /= 2;
        for (int i = 0; i < allCharacters.length(); i++) {
            System.out.println(allCharacters.substring(i, i + 1) + ": " + frequency[i] + " (" + ((double) frequency[i] / (double) total) + ")");
        }

        System.out.println("Total amount of characters in output: " + total);

        return;
    }

    public static void main(String args[]) {
        if (args.length < 1) {
            System.out.println("Please enter the file to read in as an argument.\n");
            return;
        }

        File file = new File(args[0]);
        Scanner dataScanner;
        try {
            dataScanner = new Scanner(file);
        } catch (FileNotFoundException fnfe) {
            System.out.println("Could not open " + args[0]);
            return;
        }

        String data = dataScanner.nextLine();

        if (data.length() == 0) {
            System.out.println(args[0] + " contained no data.");
            return;
        }

        String allCharacters = charactersPresent(data);
        int [] frequency = countFrequency(data, allCharacters);

        outputData(allCharacters, frequency);

        return;
    }
}
